package order;

/**
 * 桶排序：
 * 求解出现频率最多的k个元素
 *     先将元素添加到 map 字典中
 */
import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;

/**
 * @Author Janson
 * @Date 2022/2/10 16:54
 * @Version 1.0
 */
public class Order2_TopKFrequent {
    public static void main(String[] args) {
        //题目给出的数据
        int[] nums = new int[]{1, 1, 1, 2, 2, 3};
        //测试数据
        //int[] nums = new int[]{1,3,1,2,3,3,3,2,1,3,2,1,2,3};
        int k = 2;
        //1.第一步：采用map字典，统计同一个数字出现的次数
        Map<Integer, Integer> frequencyForNum = new HashMap<>();
        for (int num : nums) {
            /**
             * 这一步需要注意，关键的一步！  功能：统计同一个数字出现的次数
             * 执行的时候，比如第一次获取key=1的 值（value），此时为空，则返回0，
             * 后边在+1，这样，key=1出现的次数就是 1 次了，key=1再一次出现时，
             * 此时获取key=1的值（value）为1，后边在+1，就变成2了，说明 1 这个数出现了两次
             */

            frequencyForNum.put(num, frequencyForNum.getOrDefault(num, 0) + 1);
        }
        //2.第二步：装桶,将键值对的 value 作为集合数组的下表，key 作为集合数组的值，从而实现桶排序
        List<Integer>[] buckets = new ArrayList[nums.length + 1];
        for (int key : frequencyForNum.keySet()) {
            int frequency = frequencyForNum.get(key);
            if (buckets[frequency] == null) {
                buckets[frequency] = new ArrayList<>();
            }
            buckets[frequency].add(key);
            System.out.println(buckets[frequency]);
        }
        //3.将题目要求的频率最多的 k 个元素存放在集合中,逆序进行
        List<Integer> topK = new ArrayList<>();
        for (int i = buckets.length - 1; i >= 0 && topK.size() < k; i--) {
            if (buckets[i] == null)
                continue;

            /**
             * //有bug
             * topK.addAll(buckets[i]);
             * for (int j: buckets[i]){
             *    System.out.println("原数："+ j +"  出现次数："+i);
             * }
             * */
            //该步骤功能：防止出现 相同次数最多的元素时，造成返回结果超过 k 个元素
            if (buckets[i].size() <= k - topK.size()) {
                topK.addAll(buckets[i]);
            } else {
                topK.addAll(buckets[i].subList(0, k - topK.size()));
            }

            for (int j : buckets[i]) {
                System.out.println("原数：" + j + "  出现次数：" + i);
            }
        }
            //4.输出结果
            System.out.printf("出现次数最多的%d个数：\n", k);
            for (int j = 0; j < topK.size(); j++) {
                System.out.print(topK.get(j) + "  ");
            }

    }
}
